package com.weifly.jettycn.service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.weifly.jettycn.JettycnUtil;
import com.weifly.jettycn.dao.CatalogDao;
import com.weifly.jettycn.dao.ProjectDao;
import com.weifly.jettycn.dao.ReleaseDao;
import com.weifly.jettycn.domain.Catalog;
import com.weifly.jettycn.domain.Project;
import com.weifly.jettycn.domain.Release;
import com.weifly.jettycn.util.CallResult;
import com.weifly.jettycn.util.PageInfo;
import com.weifly.jettycn.util.QueryInfo;
import com.weifly.jettycn.util.TreeNode;

/**
 * 项目服务
 * 
 * @author weijx
 * @date 2011-10-05
 */
public class ProjectService implements IProjectService {
	
	private static final Log log = LogFactory.getLog(ProjectService.class);

	private CatalogDao catalogDao;
	
	private ProjectDao projectDao;
	
	private ReleaseDao releaseDao;
	
	/**
	 * 项目分类列表
	 */
	private List<TreeNode> catalogList;
	private Map<String, TreeNode> catalogMap;
	
	public List<TreeNode> getCatalogCache(){
		return this.catalogList;
	}
	
	public List<TreeNode> getCatalogLevel(String catalogid) {
		List<TreeNode> nodeList = new ArrayList<TreeNode>();
		TreeNode node = this.catalogMap.get(catalogid);
		if(node==null){
			return nodeList;
		}
		TreeNode tmp = node;
		while(tmp!=null){
			nodeList.add(0, tmp);
			tmp = tmp.getParent();
		}
		return nodeList;
	}
	
	public Catalog getCatalog(String catalogid){
		TreeNode node = this.catalogMap.get(catalogid);
		if(node!=null){
			return (Catalog)node.getTarget();
		}
		return null;
	}
	
	public CallResult insertCatalog(Catalog catalog) {
		CallResult result = new CallResult();
		
		if(StringUtils.isBlank(catalog.getName())){
			result.setSuccess(false);
			result.addMessage("名称不能为空");
			return result;
		}
		List<Catalog> catalogList = this.catalogDao.findCatalogByName(catalog.getName());
		if(catalogList.size()>0){
			result.setSuccess(false);
			result.addMessage("名称重复");
			return result;
		}
		catalog.setCatalogid(JettycnUtil.getUuid());
		this.catalogDao.insertCatalog(catalog);
		this.reloadCatalogCache();
		return result;
	}
	
	public CallResult updateCatalog(Catalog catalog) {
		CallResult result = new CallResult();
		
		if(StringUtils.isBlank(catalog.getCatalogid())){
			result.setSuccess(false);
			result.addMessage("id不能为空");
			return result;
		}
		TreeNode node = this.catalogMap.get(catalog.getCatalogid());
		if(node==null){
			result.setSuccess(false);
			result.addMessage("项目类别不存在");
			return result;
		}
		if(StringUtils.isBlank(catalog.getName())){
			result.setSuccess(false);
			result.addMessage("名称不能为空");
			return result;
		}
		if(StringUtils.isNotBlank(catalog.getParentid())){
			List<TreeNode> nodeList = this.getCatalogLevel(catalog.getParentid());
			for(TreeNode tn : nodeList){
				Catalog cl = (Catalog)tn.getTarget();
				if(cl.getCatalogid().equals(catalog.getCatalogid())){
					result.setSuccess(false);
					result.addMessage("父类别不能包含自身");
					return result;
				}
			}
		}
		List<Catalog> catalogList = this.catalogDao.findCatalogByName(catalog.getName());
		for(Catalog cc : catalogList){
			if(!cc.getCatalogid().equals(catalog.getCatalogid())){
				result.setSuccess(false);
				result.addMessage("名称重复");
				return result;
			}
		}
		
		Catalog cataInCache = (Catalog)node.getTarget();
		boolean cataEqual = catalogEquals(catalog, cataInCache);
		if(!cataEqual){
			log.debug("update catalog : " + catalog.getCatalogid());
			this.catalogDao.updateCatalog(catalog);
			this.reloadCatalogCache();
		}
		return result;
	}
	
	private boolean catalogEquals(Catalog c1, Catalog c2){
		if(!JettycnUtil.stringEquals(c1.getCatalogid(), c2.getCatalogid())){
			return false;
		}
		if(!JettycnUtil.stringEquals(c1.getParentid(), c2.getParentid())){
			return false;
		}
		if(!JettycnUtil.stringEquals(c1.getName(), c2.getName())){
			return false;
		}
		if(c1.isLeaf()!=c2.isLeaf()){
			return false;
		}
		if(c1.getOrder()!=c2.getOrder()){
			return false;
		}
		return true;
	}
	
	public CallResult deleteCatalog(String catalogid) {
		CallResult result = new CallResult();
		
		if(StringUtils.isBlank(catalogid)){
			result.setSuccess(false);
			result.addMessage("id为空");
			return result;
		}
		TreeNode node = this.catalogMap.get(catalogid);
		if(node==null){
			result.setSuccess(false);
			result.addMessage("项目分类不存在");
			return result;
		}
		// 查找catalog下是否有项目
		List<String> cl = new ArrayList<String>();
		countCatalog(cl, node);
		int projectCount = this.projectDao.getProjectCountor(cl);
		if(projectCount>0){
			result.setSuccess(false);
			result.addMessage("分类下还有" + projectCount + "个项目，不能删除");
			return result;
		}
		
		this.catalogDao.deleteCatalog(catalogid);
		this.reloadCatalogCache();
		
		return result;
	}
	
	public static void countCatalog(List<String> cl, TreeNode node){
		Catalog cc = (Catalog)node.getTarget();
		cl.add(cc.getCatalogid());
		if(node.getChildList()!=null){
			for(TreeNode subNode : node.getChildList()){
				countCatalog(cl, subNode);
			}
		}
	}
	
	public PageInfo queryProjectList(QueryInfo queryInfo, List<String> catalogList){
		List<Project> proList = projectDao.queryProjectList(queryInfo, catalogList);
		int proCountor = projectDao.getProjectCountor(catalogList);
		PageInfo pi = new PageInfo();
		pi.setTotal(proCountor);
		pi.setPage(queryInfo.getPage());
		pi.setPageCount(queryInfo.getPageCount());
		pi.setDataList(proList);
		
		return pi;
	}
	
	public void reloadCatalogCache(){
		List<TreeNode> cataList = new ArrayList<TreeNode>();
		Map<String, TreeNode> cataMap = new LinkedHashMap<String, TreeNode>();
		List<Catalog> clist = catalogDao.getCatalogList();
		// 寻找根节点
		for(Catalog c : clist){
			if(c.getParentid()==null){
				TreeNode n = new TreeNode();
				n.setTarget(c);
				cataList.add(n);
				cataMap.put(c.getCatalogid(), n);
			}
		}
		sortNodeList(cataList);
		// 建立树状结构
		for(TreeNode n : cataList){
			buildNodeTree(n, clist, cataMap, 1);
		}
		// 统计计数器
		QueryInfo queryInfo = new QueryInfo();
		queryInfo.setPage(-1);
		List<Project> projectList = projectDao.queryProjectList(queryInfo, null);
		for(Project p : projectList){
			if(StringUtils.isNotBlank(p.getCatalogid())){
				TreeNode tn = cataMap.get(p.getCatalogid());
				if(tn!=null){
					TreeNode tmp = tn;
					while(tmp!=null){
						tmp.setCounter(tmp.getCounter() + 1);
						tmp = tmp.getParent();
					}
				}
			}
		}
		
		this.catalogList = cataList;
		this.catalogMap = cataMap;
	}
	
	private void buildNodeTree(TreeNode n, List<Catalog> clist, Map<String, TreeNode> cataMap, int level){
		Catalog pc = (Catalog)n.getTarget();
		// System.out.println(level+ " : " + pc.getName());
		for(Catalog c : clist){
			if(pc.getCatalogid().equals(c.getParentid())){
				TreeNode childNode = new TreeNode();
				childNode.setParent(n);
				if(n.getChildList()==null){
					n.setChildList(new ArrayList<TreeNode>());
				}
				n.getChildList().add(childNode);
				childNode.setTarget(c);
				cataMap.put(c.getCatalogid(), childNode);
				
				buildNodeTree(childNode, clist, cataMap, level+1);
			}
		}
		sortNodeList(n.getChildList());
	}
	
	private void sortNodeList(List<TreeNode> nodeList){
		if(nodeList==null || nodeList.isEmpty()){
			return ;
		}
		Collections.sort(nodeList, new Comparator<TreeNode>(){
			
			public int compare(TreeNode tn1, TreeNode tn2) {
				Catalog c1 = (Catalog)tn1.getTarget();
				Catalog c2 = (Catalog)tn2.getTarget();
				return c1.getOrder() - c2.getOrder();
			}
			
		});
	}
	
	public CallResult insertProject(Project project) {
		CallResult result = new CallResult();
		
		if(StringUtils.isBlank(project.getName())){
			result.setSuccess(false);
			result.addMessage("名称不能为空");
			return result;
		}
		if(StringUtils.isBlank(project.getDescription())){
			result.setSuccess(false);
			result.addMessage("描述不能为空");
			return result;
		}
		List<Project> projectList = this.projectDao.findProjectByName(project.getName());
		if(projectList.size()>0){
			result.setSuccess(false);
			result.addMessage("名称重复");
			return result;
		}
		project.setPrjid(JettycnUtil.getUuid());
		project.setUpdate(new Date());
		this.projectDao.insertProject(project);
		this.reloadCatalogCache();
		return result;
	}
	
	public CallResult updateProject(Project project) {
		CallResult result = new CallResult();
		
		if(StringUtils.isBlank(project.getPrjid())){
			result.setSuccess(false);
			result.addMessage("id不能为空");
			return result;
		}
		Project projectInDB = this.projectDao.getProject(project.getPrjid());
		if(projectInDB==null){
			result.setSuccess(false);
			result.addMessage("项目不存在");
			return result;
		}
		if(StringUtils.isBlank(project.getName())){
			result.setSuccess(false);
			result.addMessage("名称不能为空");
			return result;
		}
		if(StringUtils.isBlank(project.getDescription())){
			result.setSuccess(false);
			result.addMessage("描述不能为空");
			return result;
		}
		List<Project> projectList = this.projectDao.findProjectByName(project.getName());
		for(Project pp: projectList){
			if(!pp.getPrjid().equals(project.getPrjid())){
				result.setSuccess(false);
				result.addMessage("名称重复");
				return result;
			}
		}
		
		boolean proEqual = projectEquals(project, projectInDB);
		if(!proEqual){
			log.debug("update project : " + project.getPrjid());
			this.projectDao.updateProject(project);
			this.reloadCatalogCache();
		}
		return result;
	}
	
	private boolean projectEquals(Project p1, Project p2){
		if(!JettycnUtil.stringEquals(p1.getPrjid(), p2.getPrjid())){
			return false;
		}
		if(!JettycnUtil.stringEquals(p1.getName(), p2.getName())){
			return false;
		}
		if(!JettycnUtil.stringEquals(p1.getHomepage(), p2.getHomepage())){
			return false;
		}
		if(!JettycnUtil.stringEquals(p1.getAuthor(), p2.getAuthor())){
			return false;
		}
		if(!JettycnUtil.stringEquals(p1.getDescription(), p2.getDescription())){
			return false;
		}
		if(!JettycnUtil.stringEquals(p1.getCatalogid(), p2.getCatalogid())){
			return false;
		}
		return true;
	}
	
	public Project getProject(String projectid) {
		return this.projectDao.getProject(projectid);
	}
	
	public CallResult deleteProject(String projectid) {
		CallResult result = new CallResult();
		
		if(StringUtils.isBlank(projectid)){
			result.setSuccess(false);
			result.addMessage("project标识为空");
			return result;
		}
		
		Project pro = this.projectDao.getProject(projectid);
		if(pro==null){
			result.setSuccess(false);
			result.addMessage("项目不存在");
			return result;
		}
		
		this.projectDao.deleteProject(projectid);
		
		return result;
	}
	
	public PageInfo queryReleaseList(String projectid, QueryInfo queryInfo) {
		List<Release> proList = releaseDao.queryReleaseList(projectid, queryInfo);
		int relCountor = releaseDao.getReleaseCountor(projectid);
		PageInfo pi = new PageInfo();
		pi.setTotal(relCountor);
		pi.setPage(queryInfo.getPage());
		pi.setPageCount(queryInfo.getPageCount());
		pi.setDataList(proList);
		
		return pi;
	}
	
	public CallResult insertRelease(Release release) {
		CallResult result = new CallResult();
		
		if(StringUtils.isBlank(release.getPrjid())){
			result.setSuccess(false);
			result.addMessage("项目id不能为空");
			return result;
		}
		if(StringUtils.isBlank(release.getVersion())){
			result.setSuccess(false);
			result.addMessage("版本不能为空");
			return result;
		}
		if(release.getPublishdate()==null){
			result.setSuccess(false);
			result.addMessage("发布日期不能为空");
			return result;
		}
		release.setReleaseid(JettycnUtil.getUuid());
		this.releaseDao.insertRelease(release);
		return result;
	}
	
	public Release getRelease(String releaseid) {
		return this.releaseDao.getRelease(releaseid);
	}
	
	public CallResult updateRelease(Release release) {
		CallResult result = new CallResult();
		
		if(StringUtils.isBlank(release.getReleaseid())){
			result.setSuccess(false);
			result.addMessage("release id不能为空");
			return result;
		}
		if(StringUtils.isBlank(release.getPrjid())){
			result.setSuccess(false);
			result.addMessage("项目id不能为空");
			return result;
		}
		if(StringUtils.isBlank(release.getVersion())){
			result.setSuccess(false);
			result.addMessage("版本不能为空");
			return result;
		}
		if(release.getPublishdate()==null){
			result.setSuccess(false);
			result.addMessage("发布日期不能为空");
			return result;
		}
		Release relInDB = this.releaseDao.getRelease(release.getReleaseid());
		if(relInDB==null){
			result.setSuccess(false);
			result.addMessage("release不存在");
			return result;
		}
		this.releaseDao.updateRelease(release);
		return result;
	}
	
	public CallResult deleteRelease(String releaseid) {
		CallResult result = new CallResult();
		
		if(StringUtils.isBlank(releaseid)){
			result.setSuccess(false);
			result.addMessage("release id不能为空");
			return result;
		}
		Release relInDB = this.releaseDao.getRelease(releaseid);
		if(relInDB==null){
			result.setSuccess(false);
			result.addMessage("release不存在");
			return result;
		}
		this.releaseDao.deleteRelease(releaseid);
		
		return result;
	}
	
	public void init(){
		reloadCatalogCache();
	}

	public void setCatalogDao(CatalogDao catalogDao) {
		this.catalogDao = catalogDao;
	}

	public void setProjectDao(ProjectDao projectDao) {
		this.projectDao = projectDao;
	}

	public void setReleaseDao(ReleaseDao releaseDao) {
		this.releaseDao = releaseDao;
	}
	
}
